﻿using System.Collections.ObjectModel;
using System.Data.Entity;
using System.Linq;
using InseSoft.Models;
using InseSoft.Models.Entities;
using InseSoft.ViewModels;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Ninject;

namespace InseSoft.Tests.Unit.ViewModels
{
    [TestClass]
    public class CatalogEntityViewModelTest
    {
        private readonly IKernel kernel;
        private ICatalogEntityViewModel instance;

        public CatalogEntityViewModelTest()
        {
            kernel = TestHelper.SetupDIKernel();
        }

        [TestInitialize]
        public void TestInitialize()
        {
            instance = new CatalogEntityViewModel<Empresa>();
            kernel.Inject(instance);
            instance.Initialize();
        }
        
        [TestMethod]
        public void NewCanExecute_ItemsWithNonZeroId_True()
        {
            var catalogSearchStub = new Mock<ICatalogSearchViewModel>();
            instance.CatalogSearchViewModel = catalogSearchStub.Object;
            var recordList = CreateEmpresaList();
            catalogSearchStub.Setup(c => c.RecordList).Returns(recordList);
            
            Assert.IsTrue(instance.NewCommand.CanExecute(null));
        }

        [TestMethod]
        public void NewCanExecute_ItemWithIdEqualsZero_False()
        {
            var catalogSearchStub = new Mock<ICatalogSearchViewModel>();
            instance.CatalogSearchViewModel = catalogSearchStub.Object;
            var recordList = CreateEmpresaList();
            recordList[0].Id = 0;
            catalogSearchStub.Setup(c => c.RecordList).Returns(recordList);

            Assert.IsFalse(instance.NewCommand.CanExecute(null));
        }

        [TestMethod]
        public void NewExecute_NewEmpresa_SessionEmpresaNotAttachedToContext()
        {
            var contextMock = new Mock<IInseContext>();
            var dbSetMock = new Mock<IDbSet<Empresa>>();
            contextMock.Setup(x => x.Set<Empresa>()).Returns(dbSetMock.Object);
            kernel.Rebind<IInseContext>().ToMethod<IInseContext>(c => contextMock.Object);
            var session = kernel.Get<ApplicationSession>();
            session.Empresa = new Empresa { Id = int.MaxValue };
            instance.DbContext = contextMock.Object;
            dbSetMock.Setup(d => d.Attach(session.Empresa));
            
            instance.NewCommand.Execute(null);
            dbSetMock.Verify(d => d.Attach(session.Empresa), Times.Never());
        }

        [TestMethod]
        public void NewExecute_NewLinea_SessionEmpresaAttachedToContext()
        {
            instance = new CatalogEntityViewModel<Linea>();
            kernel.Inject(instance);
            var session = kernel.Get<ApplicationSession>();
            session.Empresa = new Empresa { Id = int.MaxValue };

            var mock = new Mock<IDbSet<Empresa>>();
            mock.Setup(m => m.Attach(session.Empresa));
            instance.DbContext.Empresas = mock.Object;
            instance.Initialize();

            instance.NewCommand.Execute(null);

            mock.Verify(m => m.Attach(session.Empresa), Times.Once());
        }
        
        #region Helpers

        private ObservableCollection<CatalogEntity> CreateEmpresaList()
        {
            return new ObservableCollection<CatalogEntity>
            {
                new Empresa{Id=1, Nombre = "San José"},
                new Empresa{Id=2, Nombre = "Alajuela"},
                new Empresa{Id=3, Nombre = "Cartago"},
                new Empresa{Id=4, Nombre = "Heredia"},
            };
        }
        
        #endregion
    }
}
